import { MODEL_NAME } from '../../constants/model-names';
import { EVENTS, type IEventBus } from '../../events';
import type { BaseSnapshot } from '../../systems/save';
import { BaseModel } from '../base';
import { REALM_LEVEL_LIST, type RealmLevel } from '../../data/realm';

export interface RealmV1 extends BaseSnapshot {
  version: 1;
  realm: number;
  currentExp: number;
  totalExp: number;
}

export type RealmSnapshot = RealmV1;

export type RealmSnapshotOld = RealmV1;

export interface RealmState {
  realmInfo: {
    name: string;
    requiredExp: number;
  } | null;
  nextRealmInfo: {
    name: string;
    requiredExp: number;
  } | null;
  currentExp: number;
  totalExp: number;
  canBreakRealm: boolean;
  progress: number;
}

export class RealmModel extends BaseModel {
  public name = MODEL_NAME.REALM;
  /** 当前境界 */
  private realm = 0;
  /** 当前修为 */
  private currentExp = 0;
  /** 总修为 */
  private totalExp = 0;
  /** 境界映射 */
  private readonly realmMap = new Map<number, RealmLevel>();
  private bus: IEventBus;

  constructor(bus: IEventBus) {
    super();
    this.bus = bus;
    for (let i = 0; i < REALM_LEVEL_LIST.length; i++) {
      this.realmMap.set(i, REALM_LEVEL_LIST[i]!);
    }
  }

  public getRealm() {
    return this.realm;
  }

  /** 增加修为 */
  public addExp(exp: number) {
    this.currentExp += exp;
    this.totalExp += exp;
    this.bus.emit(EVENTS.REALM_STATE_UPDATE);
  }

  /** 减少修为 */
  public minusExp(exp: number) {
    this.currentExp = Math.max(0, this.currentExp - exp);
    this.bus.emit(EVENTS.REALM_STATE_UPDATE);
  }

  /** 消耗修为(使用修为不得大于当前修为) */
  public consumeExp(exp: number) {
    if (this.currentExp < exp) return;
    this.minusExp(exp);
  }

  /** 突破境界 */
  public breakRealm() {
    const nextRealmInfo = this.getNextRealmInfo();
    if (!this.canBreakRealm() || !nextRealmInfo) return false;
    this.realm += 1;
    this.currentExp -= nextRealmInfo.requiredExp;
    this.bus.emit(EVENTS.REALM_STATE_UPDATE);
    return true;
  }

  /** 获取当前境界信息 */
  public getCurrentRealmInfo() {
    const currentRealmInfo = this.realmMap.get(this.realm);
    return currentRealmInfo;
  }

  /** 获取下一境界信息 */
  public getNextRealmInfo() {
    const nextRealmInfo = this.realmMap.get(this.realm + 1);
    return nextRealmInfo;
  }

  /** 是否可以突破 */
  public canBreakRealm() {
    const nextRealm = this.realmMap.get(this.realm + 1);
    if (!nextRealm) return false;
    return this.currentExp >= nextRealm.requiredExp;
  }

  public getState() {
    const currentRealmInfo = this.getCurrentRealmInfo();
    const nextRealmInfo = this.getNextRealmInfo();
    let progress = 0;
    if (nextRealmInfo) {
      progress = Math.min(1, this.currentExp / nextRealmInfo.requiredExp);
      progress = Math.round(progress * 100);
    }
    return {
      realmInfo: currentRealmInfo
        ? {
            name: currentRealmInfo.name,
            requiredExp: currentRealmInfo.requiredExp,
          }
        : null,
      nextRealmInfo: nextRealmInfo
        ? {
            name: nextRealmInfo.name,
            requiredExp: nextRealmInfo.requiredExp,
          }
        : null,
      currentExp: this.currentExp,
      totalExp: this.totalExp,
      canBreakRealm: this.canBreakRealm(),
      progress,
    };
  }

  public getSnapshot(): RealmSnapshot {
    return {
      version: 1,
      realm: this.realm,
      currentExp: this.currentExp,
      totalExp: this.totalExp,
    };
  }

  public get uiState(): RealmState {
    return this.getState();
  }

  public save(): RealmSnapshot {
    return this.getSnapshot();
  }

  public load(snapshot: RealmSnapshot) {
    this.realm = snapshot.realm;
    this.currentExp = snapshot.currentExp;
    this.totalExp = snapshot.totalExp;
  }
}
